﻿/**
 * @file SynchronizedQueue.hpp
 * @brief SSD仿真系统IPC同步队列模板，支持多进程安全的队列操作。
 */
#ifndef __SynchronizedQueue_h__
#define __SynchronizedQueue_h__

#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/deque.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/sync/interprocess_condition.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <sstream>

namespace bip = boost::interprocess;

/**
 * @class lock
 * @brief RAII风格的互斥锁封装类，自动管理互斥锁的加解锁。
 */
class lock
{
public:
    /**
     * @brief 构造函数，自动加锁。
     * @param m 互斥锁引用
     */
    lock(bip::interprocess_mutex &m)
        : _Mutex(&m), _Locked(false)
    {
        _Mutex->lock();
        _Locked = true;
    }

    /**
     * @brief 析构函数，自动解锁。
     */
    ~lock()
    {
        try
        {
            if (_Locked && _Mutex)
                _Mutex->unlock();
        }
        catch (...)
        {
        }
    }

private:
    bip::interprocess_mutex *_Mutex; /**< 互斥锁指针 */
    bool _Locked;                    /**< 是否已加锁 */
};

/**
 * @class SynchronizedQueue
 * @brief 多进程安全的同步队列模板，支持队列操作与条件变量等待。
 * @tparam T 队列元素类型
 */
template <class T>
class SynchronizedQueue
{
public:
    typedef bip::allocator<T, bip::managed_shared_memory::segment_manager> allocator_type; /**< 队列分配器类型 */

private:
    bip::deque<T, allocator_type> _Queue;               /**< 队列容器 */
    mutable bip::interprocess_mutex _IoMutex;           /**< 互斥锁 */
    mutable bip::interprocess_condition _WaitCondition; /**< 条件变量 */

public:
    /**
     * @brief 构造函数，初始化队列分配器。
     * @param alloc 分配器
     */
    SynchronizedQueue(allocator_type alloc) : _Queue(alloc) {}

    /**
     * @brief 推入元素到队列尾部。
     * @param element 元素
     */
    void push(T element)
    {
        lock lock(_IoMutex);
        _Queue.push_back(element);
        _WaitCondition.notify_one();
    }
    /**
     * @brief 检查队列是否为空。
     * @return 是否为空
     */
    bool empty() const
    {
        lock lock(_IoMutex);
        return _Queue.empty();
    }

    /**
     * @brief 弹出队列头部元素。
     * @param element 弹出元素存放位置
     * @return 是否弹出成功
     */
    bool pop(T &element)
    {
        lock lock(_IoMutex);

        if (_Queue.empty())
        {
            return false;
        }

        element = _Queue.front();
        _Queue.pop_front();
        return true;
    }

    /**
     * @brief 获取队列当前元素数量。
     * @return 队列大小
     */
    unsigned int sizeOfQueue() const
    {
        // try to lock the mutex
        lock lock(_IoMutex);
        return _Queue.size();
    }

    /**
     * @brief 等待队列非空并弹出元素。
     * @param element 弹出元素存放位置
     */
    void waitAndPop(T &element)
    {
        lock lock(_IoMutex);

        while (_Queue.empty())
        {
            _WaitCondition.wait(lock);
        }

        element = _Queue.front();
        _Queue.pop();
    }
};

#endif